// Copyright Epic Games, Inc. All Rights Reserved.

const process = require('process');
const fs = require('fs');
const { Console } = require('console');
const path = require('path');

var loggers = [];
var logFunctions = [];
var logColorFunctions = [];

//调用位置获取函数
function getCallerLocation() {
  try {
    const stack = new Error().stack.split('\n');
    // 查找第一个非日志模块的调用帧
    for (let i = 3; i < stack.length; i++) {
      const line = stack[i].trim();
      const match = line.match(/\((.*):(\d+):(\d+)\)$/) || line.match(/at (.*):(\d+):(\d+)$/);

      if (match) {
        const filePath = match[1];
        const filename = path.basename(filePath);

        // 跳过日志模块自身的调用
        if (filename !== 'logger.js' && !filePath.includes('logger.js')) {
          return `${filename}:${match[2]}`;
        }
      }
    }
  } catch {
    // 错误处理
  }
  return 'unknown';
}

console.log = function (msg, ...args) {
  const location = getCallerLocation();
  logFunctions.forEach((logFunction) => {
    logFunction(`[${location}] ${msg}`, ...args);
  });
};

console.logColor = function (color, msg, ...args) {
  const location = getCallerLocation();
  logColorFunctions.forEach((logColorFunction) => {
    logColorFunction(color, `[${location}] ${msg}`, ...args);
  });
};

const AllAttributesOff = '\x1b[0m';
const BoldOn = '\x1b[1m';
const Black = '\x1b[30m';
const Red = '\x1b[31m';
const Green = '\x1b[32m';
const Yellow = '\x1b[33m';
const Blue = '\x1b[34m';
const Magenta = '\x1b[35m';
const Cyan = '\x1b[36m';
const White = '\x1b[37m';

/**
 * Pad the start of the given number with zeros so it takes up the number of digits.
 * e.g. zeroPad(5, 3) = '005' and zeroPad(23, 2) = '23'.
 */
function zeroPad(number, digits) {
  return number.toString().padStart(digits, '0');
}

/**
 * Create a string of the form 'YEAR.MONTH.DATE.HOURS.MINUTES.SECONDS'.
 */
function dateTimeToString() {
  const date = new Date();
  return [
    date.getFullYear(),
    zeroPad(date.getMonth() + 1, 2),
    zeroPad(date.getDate(), 2),
    zeroPad(date.getHours(), 2),
    zeroPad(date.getMinutes(), 2),
    zeroPad(date.getSeconds(), 2),
  ].join('.');
}

/**
 * Create a string of the form 'YEAR-MONTH-DATE HOURS:MINUTES:SECONDS.MILLISECONDS'.
 */
function timeToString() {
  const date = new Date();
  return [
    `${date.getFullYear()}-${zeroPad(date.getMonth() + 1, 2)}-${zeroPad(date.getDate(), 2)}`,
    `${zeroPad(date.getHours(), 2)}:${zeroPad(date.getMinutes(), 2)}:${zeroPad(date.getSeconds(), 2)}.${zeroPad(date.getMilliseconds(), 3)}`,
  ].join(' ');
}

function RegisterFileLogger(logPath) {
  const logsDir = logPath || './logs';

  if (!fs.existsSync(logsDir)) {
    fs.mkdirSync(logsDir, { recursive: true });
  }

  const logFilePath = path.join(logsDir, `${dateTimeToString()}.log`);
  const output = fs.createWriteStream(logFilePath);
  const fileLogger = new Console(output);

  logFunctions.push(function (msg, ...args) {
    fileLogger.log(`${timeToString()} ${msg}`, ...args);
  });

  logColorFunctions.push(function (color, msg, ...args) {
    fileLogger.log(`${timeToString()} ${msg}`, ...args);
  });

  loggers.push(fileLogger);
  console.log(`文件日志已注册到: ${logFilePath}`);
}

function RegisterConsoleLogger() {
  const consoleLogger = new Console(process.stdout, process.stderr);

  logFunctions.push(function (msg, ...args) {
    consoleLogger.log(`${timeToString()} ${msg}`, ...args);
  });

  logColorFunctions.push(function (color, msg, ...args) {
    consoleLogger.log(`${BoldOn}${color}${timeToString()} ${msg}${AllAttributesOff}`, ...args);
  });
  loggers.push(consoleLogger);
  console.log('控制台日志已注册');
}

module.exports = {
  //Functions
  RegisterFileLogger,
  RegisterConsoleLogger,

  //Variables
  AllAttributesOff,
  BoldOn,
  Black,
  Red,
  Green,
  Yellow,
  Blue,
  Magenta,
  Cyan,
  White,
};
